package com.xindacloud.sms.portal.controller;


import com.clxcommunications.xms.api.BatchDeliveryReport;
import com.google.gson.Gson;
import com.xindacloud.sms.portal.component.ReceiveDLRConvertComponent;
import com.xindacloud.sms.portal.dto.DomesticSmsReportRequestBodyBO;
import com.xindacloud.sms.portal.entity.SmsDeliveryReceipt;
import com.xindacloud.sms.portal.exception.ServiceException;
import com.xindacloud.sms.portal.properties.EndpointProperties;
import com.xindacloud.sms.portal.utils.UnionResultHelp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.List;

@Api(tags = {"短信交货报告接口模块"})
@Slf4j
@RestController
public class ReceiveDLRController {

    final ReceiveDLRConvertComponent receiveDLRConvertComponent;

    final EndpointProperties endpointProperties;

    String adapterGateway;

    @Autowired
    public ReceiveDLRController(ReceiveDLRConvertComponent receiveDLRConvertComponent, EndpointProperties endpointProperties) {
        this.receiveDLRConvertComponent = receiveDLRConvertComponent;
        this.endpointProperties = endpointProperties;
        adapterGateway = endpointProperties.getAdapterGateway();
    }

    @ApiOperation(value = "Nexmo交货报告")
    @GetMapping("/webhooks/delivery-report")
    public void getDeliveryReceipt(HttpServletRequest req, HttpServletResponse resp) {
        log.info("===== Execute Get Method DLR");
        executeNexMoDLR(req, resp);
    }

    @ApiOperation(value = "Nexmo交货报告")
    @PostMapping("/webhooks/delivery-report")
    public void postDeliveryReceipt(HttpServletRequest req, HttpServletResponse resp) {
        log.info("===== Nexmo Execute Post Method DLR:{}", new Gson().toJson(req.getParameterMap()));
        executeNexMoDLR(req, resp);
    }


    private void executeNexMoDLR(HttpServletRequest req, HttpServletResponse resp) {
        @NotNull final SmsDeliveryReceipt receiveDLRDTO = receiveDLRConvertComponent.getNexmoReceiveDLRDTO(req);
        log.info("### Nexmo推送报告：messageId:{},号码为:{}", receiveDLRDTO.getMessageId(), receiveDLRDTO.getSentTo());
        sendPostRequest(receiveDLRDTO, endpointProperties.getAdapterNexmoReportPath());


    }


    @ApiOperation(value = "Sinch交货报告")
    @PostMapping(path = "/sinch/delivery-report")
    public ResponseEntity getSinchReceiveReport(@RequestBody BatchDeliveryReport report) {
        @NotNull final List<SmsDeliveryReceipt> sinchReceiveDLRDTO = receiveDLRConvertComponent.getSinchReceiveDLRDTO(report);
        for (SmsDeliveryReceipt deliveryReceipt : sinchReceiveDLRDTO) {
            log.info("### Sinch推送报告：messageId:{},号码为:{}", deliveryReceipt.getMessageId(), deliveryReceipt.getSentTo());
            sendPostRequest(deliveryReceipt, endpointProperties.getAdapterSinchReportPath());
        }
        return ResponseEntity.ok().build();
    }

    @ApiOperation(value = "CM交货报告")
    @GetMapping("/cm/delivery-report")
    public ResponseEntity getCMDeliveryReceipt(HttpServletRequest req, HttpServletResponse resp) {

        @NotNull final SmsDeliveryReceipt cmReceiveDLRDTO = receiveDLRConvertComponent.getCMReceiveDLRDTO(req);
        log.info("### CM推送报告：messageId:{},号码为:{}", cmReceiveDLRDTO.getMessageId(), cmReceiveDLRDTO.getSentTo());
        sendPostRequest(cmReceiveDLRDTO, endpointProperties.getAdapterCmReportPath());
        return ResponseEntity.ok().build();
    }


    @ApiOperation(value = "国内交货报告")
    @PostMapping("/domestic/api/sms/report")
    public ResponseEntity geDomesticDeliveryReceipt(@RequestBody DomesticSmsReportRequestBodyBO reportRequestBodyBO, HttpServletResponse resp) {

        @NotNull final SmsDeliveryReceipt domesticReceiveDLRDTO = receiveDLRConvertComponent.getDomesticReceiveDLRDTO(reportRequestBodyBO);
        log.info("### 国内推送报告：messageId:{},号码为:{}", domesticReceiveDLRDTO.getMessageId(), domesticReceiveDLRDTO.getSentTo());
        sendPostRequest(domesticReceiveDLRDTO, endpointProperties.getAdapterDomesticReportPath());
        return ResponseEntity.ok().build();
    }


    @ApiOperation(value = "火信云交货报告")
    @PostMapping(value = "/huoxin/delivery-report",
            produces = MediaType.APPLICATION_JSON_VALUE,
            consumes = MediaType.APPLICATION_JSON_VALUE)
    public String getHuoxinDeliveryReceipt(HttpServletRequest request, HttpServletResponse resp) {

        @NotNull final List<SmsDeliveryReceipt> huoxinReceiveDLRDTO = receiveDLRConvertComponent.getHuoxinReceiveDLRDTO(request);
        for (SmsDeliveryReceipt smsDeliveryReceipt : huoxinReceiveDLRDTO) {
            log.info("!!!  火信云推送报告：messageId:{},号码为:{}", smsDeliveryReceipt.getMessageId(), smsDeliveryReceipt.getSentTo());
            sendPostRequest(smsDeliveryReceipt, endpointProperties.getAdapterHuoxinReportPath());
        }
        return "SUCCESS";
    }


    private UnionResultHelp sendPostRequest(@NotNull SmsDeliveryReceipt smsDeliveryReceipt, String path) {
        log.info("### request path:{}", path);
        log.info("### 调用Adapter回执参数SmsDeliveryReceipt:{}", new Gson().toJson(smsDeliveryReceipt));
        final UnionResultHelp block = WebClient
                .create(adapterGateway.concat(path))
                .post()
                .accept(MediaType.APPLICATION_JSON)
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
                })
                .body(Mono.just(smsDeliveryReceipt), SmsDeliveryReceipt.class)
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, clientResponse ->
                        Mono.error(new ServiceException("推送报告异常.", clientResponse.statusCode().value()))
                )
                .onStatus(HttpStatus::is5xxServerError, clientResponse ->
                        Mono.error(new ServiceException("推送报告异常.", clientResponse.statusCode().value()))
                )
                .bodyToMono(new ParameterizedTypeReference<UnionResultHelp>() {
                })
                .block();
        log.info("response result:{}", new Gson().toJson(block));
        return block;
    }
}
